<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>01-04 变换帧测 - 监听整个对象</title>
</head>
<body>
  <h1>变换帧测 - 监听整个对象</h1>
  <h2>Vue 两大核心? 数据驱动、组件化</h2>

  数据驱动: Object.defineProperty

  如何监听整个对象

  <!-- 观测类： 让对象的每一项都变成可观测 -->
  <script>
    class Observer {
      // 数据初始化
      constructor(value) {
        console.log('Observer - constructor value=', value)
        this.value = value
        if (Array.isArray(value)) {
          // 数组
          const len = value.length
          for (let i = 0; i < len; i++) {
            const key = value[i]
            if (typeof key === 'object') {
              this.walk(key)
            } else {
              defineReactive(value, key)
            }
          }
        } else {
          // 对象
          this.walk(value)
        }
      }

      walk(obj) {
        console.log('walk - obj=', obj)
        const keys = Object.keys(obj) // 键值数组
        for (let i = 0; i < keys.length; i++) {
          const key = keys[i]
          defineReactive(obj, key, obj[key])
        }
      }
    }

    function defineReactive(obj, key, val) {
      console.log('00 defineReactive - key=', key, ' val=', val)
      if (arguments.length === 2 && key) {
        val = obj[key]
      }
      console.log('11 defineReactive - key=', key, ' val=', val)

      if (typeof val === 'object' || Array.isArray(val)) {
        new Observer(val)
      }

      Object.defineProperty(obj, key, {
        get() {
          console.log(`defineReactive -33- ${key} 属性被读取了 ${val}`)
          return val
        },
        set(newValue) {
          if (val === newValue) return
          console.log(`defineReactive -44- ${key} 属性被修改了`, val, ' newValue=', newValue)
          val = newValue
        }
      })
    }
  </script>

  <script>
    let obj = {
      name: '小明',
      age: 1,
      demo: {
        high: 1,
        b: '1'
      },
      arr:[
        {
          a1: 'arr1'
        },
        [{
          a2: 'arrObj1'
        }]
      ]
    }

    const newObj = new Observer(obj)
    // newObj.value.name = '旺旺'
    // newObj.value.age = 100

    // newObj.value.demo.high = 300
    // newObj.value.demo.b = 'srxboys'

    // newObj.value.arr[0].a1 = 'srxboys-a1'

    newObj.value.arr[1][0].a2 = 'srxboys-a2'

    console.log('最终结果: newObj=', newObj)
  </script>
</body>
</html>